#include "BluetoothDevice.h"

#include "SocketException.h"

using namespace std;

BluetoothDevice::BluetoothDevice(BLUETOOTH_DEVICE_INFO deviceInfo, HANDLE radioHandle) 
	: mDeviceInfo(deviceInfo)
	, mRadioHandle(radioHandle)
{}

BTH_ADDR BluetoothDevice::getMacAddress() {
	return mDeviceInfo.Address.ullLong;
}

BLUETOOTH_DEVICE_INFO BluetoothDevice::getDeviceInfo() {
	return mDeviceInfo;
}


vector<GUID> BluetoothDevice::getServices() {
	/*
	static const int BUFSIZE = 20;
	 GUID guids[BUFSIZE];
	 DWORD numGuids = BUFSIZE;

	 DWORD result = BluetoothEnumerateInstalledServices(mRadioHandle, &mDeviceInfo, &numGuids, guids);
	
	 return vector<GUID>(guids, guids + numGuids);
	  */
	return mServices;
}

tstring BluetoothDevice::getName() {
	return mDeviceInfo.szName;
}


void BluetoothDevice::updateServices() {
	_tprintf(_T("updating services for %.12llX\n"), getMacAddress());
	/*
    WSAQUERYSET wsaQuerySet = {0};	
    wsaQuerySet.dwSize = sizeof(WSAQUERYSET);
    wsaQuerySet.dwNameSpace = NS_BTH;	

	DWORD flags = LUP_RETURN_ALL
		| LUP_CONTAINERS 
		| LUP_FLUSHCACHE  // do a fresh search
		| LUP_RES_SERVICE
		;

	
	// device discovery
	HANDLE hLookup;
	if (::WSALookupServiceBegin(&wsaQuerySet, flags , &hLookup) 
		== SOCKET_ERROR) throw SocketException(_T("WSALookupServiceBegin()"),WSAGetLastError());

	DWORD bufSize;
	BYTE buf[1024] = {0};
	LPWSAQUERYSET resultSet = (LPWSAQUERYSET)buf;
	bufSize = sizeof(buf);

	CSADDR_INFO remoteDevice = {0};

	// print out all the results
	printf("\ndiscovered devices:\n");
	while (::WSALookupServiceNext(hLookup,  flags, &bufSize, resultSet) != SOCKET_ERROR) {	
		_tprintf(_T("%s %u\n"),resultSet->lpszServiceInstanceName, resultSet->dwNumberOfCsAddrs);

		remoteDevice = resultSet->lpcsaBuffer[0];

		tstring gs = Util::guidToString(*resultSet->lpServiceClassId);
		_tprintf(_T("UUID: %s\n"),gs.c_str());


		_tprintf( _T("Comment: %s\n"), resultSet->lpszComment);
		//BluetoothSdpEnumAttributes( resultSet->lpBlob->pBlobData, resultSet->lpBlob->cbSize, callback, 0);
	}

	// finish discovery
	if (::WSALookupServiceEnd(hLookup) 
		== SOCKET_ERROR) throw SocketException(_T("WSALookupServiceEnd()"),WSAGetLastError());
		*/

	BTH_ADDR addr = mDeviceInfo.Address.ullLong;
	
	// service discovery
	SOCKADDR_BTH btha = {0};
	btha.addressFamily = AF_BTH;
	btha.btAddr = addr;
	
	// http://msdn.microsoft.com/en-us/library/windows/desktop/aa362914(v=vs.85).aspx
	// convert the mac address of the remote device to a string
	TCHAR addrString[40];
	DWORD addrStringLen = sizeof(addrString);
	if (::WSAAddressToString( (sockaddr*)&btha, sizeof(btha), NULL, addrString, &addrStringLen)
		== SOCKET_ERROR) throw SocketException(_T("WSAAddressToString()"),WSAGetLastError());	 
	
	WSAQUERYSET serviceQuerySet = {0};
	serviceQuerySet.dwSize = sizeof(WSAQUERYSET);
	serviceQuerySet.dwNameSpace = NS_BTH; // search the bluetooth namespace
	serviceQuerySet.dwNumberOfCsAddrs = 0; // must be 0
	serviceQuerySet.lpszContext = addrString; // the mac address of the remote device as a string
	serviceQuerySet.lpServiceClassId = (LPGUID)&MYGUID; // search for this GUID

	//serviceQuerySet.lpServiceClassId = (LPGUID)&PublicBrowseGroupServiceClass_UUID; // search for this GUID


	DWORD beginFlags = LUP_FLUSHCACHE | LUP_RETURN_ALL; // initiate a SDP query
	DWORD nextFlags =  LUP_RETURN_ALL; 

	HANDLE hServiceLookup;
	if (::WSALookupServiceBegin( &serviceQuerySet, beginFlags, &hServiceLookup)
		== SOCKET_ERROR) throw SocketException(_T("WSALookupServiceBegin()"),WSAGetLastError());


	//tcout << Util::guidToString(*serviceQuerySet.lpServiceClassId) << endl;

	BYTE serviceResultBuf[1024] = {0};
	DWORD serviceResultBufSize = sizeof(serviceResultBuf);
	LPWSAQUERYSET serviceResultQuerySet = (LPWSAQUERYSET)serviceResultBuf;
	serviceResultQuerySet->dwSize = sizeof(WSAQUERYSET);
	serviceResultQuerySet->dwNameSpace = NS_BTH;

	while (::WSALookupServiceNext( hServiceLookup, nextFlags, &serviceResultBufSize, serviceResultQuerySet) != SOCKET_ERROR) {
		printf("AEGIOHEAOIGHEAOIG");
	}

	int lastError = WSAGetLastError();
	switch(lastError) {
	case WSA_E_NO_MORE: printf("no more services found\n"); break;
	default: throw SocketException(_T("WSALookupServiceNext()"),lastError);	
	};

	if (::WSALookupServiceEnd(hServiceLookup)
		== SOCKET_ERROR) throw SocketException(_T("WSALookupServiceEnd()"),WSAGetLastError());		
}

